package m3u8

import (
	"errors"
	"gitee.com/kaylee595/gkaylee/kerr"
	"gitee.com/kaylee595/m3u8/token"
	"io"
	"time"
)

// ParseMediaPlayList 解析一个媒体播放列表
func ParseMediaPlayList(r io.Reader) (*MediaPlayList, error) {
	ret := &MediaPlayList{}
	var key *Key
	var map_ *Map
	decoder := token.NewDecoder(r)
parser:
	for {
		l, err := decoder.ReadLine()
		if err != nil {
			if errors.Is(err, io.EOF) {
				break
			}
			return nil, kerr.WrapTraceStack(err)
		}
		kind := l.Kind()
		if kind == token.KindTag {
			tag, value := l.Tag()
			switch tag {
			case extXVersion:
				ret.Version = value.Value().FromUint()
			case extXTargetDuration:
				ret.TargetDuration = time.Duration(value.Value().FromUint()) * time.Second
			case extXMediaSequence:
				ret.MediaSequence = value.Value().FromUint()
			case extXPlayListType:
				ret.PlayListType = PlayListType(value.Value().String())
			case extXKey:
				key = ParseKey(value.Attributes())
			case extXMap:
				map_ = ParseMap(value.Attributes(), key)
			case extINF:
				values := value.Values()
				segments := MediaSegment{
					Sequence: ret.MediaSequence + uint64(len(ret.Segments)),
					Key:      key,
					Map:      map_,
				}
				if len(values) >= 1 {
					segments.Duration = time.Duration(values[0].FromFloat() * float64(time.Second))
					if len(values) >= 2 {
						segments.Title = values[1].FromString()
					}
				}
				mediaURI, err := decoder.ReadLine()
				if err != nil {
					if errors.Is(err, io.EOF) {
						break parser
					}
					return nil, kerr.WrapTraceStack(err)
				}
				segments.URI = mediaURI.URI()
				ret.Segments = append(ret.Segments, segments)
			case extXEndList:
				break parser
			}
		}
	}
	return ret, nil
}

// ParseMasterPlayList 解析一个主播媒体列表
func ParseMasterPlayList(r io.Reader) (*MasterPlayList, error) {
	ret := &MasterPlayList{}
	decoder := token.NewDecoder(r)
parser:
	for {
		l, err := decoder.ReadLine()
		if err != nil {
			if errors.Is(err, io.EOF) {
				break
			}
			return nil, kerr.WrapTraceStack(err)
		}
		kind := l.Kind()
		if kind == token.KindTag {
			tag, value := l.Tag()
			switch tag {
			case extXVersion:
				ret.Version = value.Value().FromUint()
			case extXStreamINF:
				attrs := value.Attributes()
				mediaURI, err := decoder.ReadLine()
				if err != nil {
					if errors.Is(err, io.EOF) {
						break parser
					}
					return nil, kerr.WrapTraceStack(err)
				}
				ret.Segments = append(ret.Segments, ParseMasterSegment(attrs, mediaURI.URI()))
			}
		}
	}
	return ret, nil
}
